package com.bootdo.common.utils;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class SXSSFWorkBookUtil {

    public static void exportSheetsForOneObj(String title, String[] headers,
                                             Map<Object, List<Object[]>> dataMap,
                                             HttpServletRequest request, HttpServletResponse response) {
        response.reset();// 清空输出流
        try {
            int rowaccess = 100;// 内存中缓存记录行数
            SXSSFWorkbook wb = new SXSSFWorkbook(rowaccess);
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");

            String filedisplay = title + ".xls";
            response.addHeader("Content-Disposition", "attachment;filename="
                    + filedisplay);
            if (request.getHeader("USER-AGENT").toLowerCase()
                    .indexOf("firefox") > 0 ? false : true) {
                filedisplay = "attachment;filename="
                        + URLEncoder.encode(filedisplay, "UTF-8");
            } else {
                filedisplay = "attachment;filename="
                        + new String(filedisplay.getBytes(), "ISO-8859-1");
            }
            response.setContentType("application/x-msdownload;charset=UTF-8");
            response.setHeader("Content-disposition", filedisplay);

            Font font = wb.createFont();
            font.setFontName("宋体");
            font.setFontHeightInPoints((short) 16);
            CellStyle style = wb.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);

            Set<Entry<Object, List<Object[]>>> entrySet = dataMap
                    .entrySet();
            for (Entry<Object, List<Object[]>> entry : entrySet) {
//            	Object key = entry.getKey();
                Sheet sheet = wb.createSheet(title);// sheet页签名
                sheet.setDefaultColumnWidth(15);// 默认宽度

                Row row = sheet.createRow((int) 0);
                for (int i = 0; i < headers.length; i++) {
                    row.createCell(i).setCellValue(headers[i]);//第一行列名
                }
                List<Object[]> list = entry.getValue();
                for (int i = 0; i < list.size(); i++) {
                    Object[] obj = list.get(i);
                    row = sheet.createRow((int) i + 1);
                    for (int j = 0; j < obj.length; j++) {
                        if (null == obj[j]) {
                            row.createCell(j).setCellValue("");
                        } else {
                            row.createCell(j).setCellValue(
                                    String.valueOf(obj[j]));
                        }
                    }
                    // 每当行数达到设置的值就刷新数据到硬盘,以清理内存
                    if (i % rowaccess == 0) {
                        ((SXSSFSheet) sheet).flushRows();
                    }
                }
            }

            OutputStream out = response.getOutputStream();
            wb.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void exportSheetsForMoreData(String title, String[] headers,
            Map<String, Object> dataMap, HttpServletRequest request,
            HttpServletResponse response) {
        response.reset();// 清空输出流
        OutputStream out = null;
        File zip = new File(getRealPath(request) + "/" + getFileName(title)
                + ".zip");// 压缩文件
        List<String> fileNames = new ArrayList<String>();// 用于存放生成的文件名称
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            String filedisplay = getFileName(title) + ".zip";
            response.addHeader("Content-Disposition", "attachment;filename="
                    + filedisplay);
            if (request.getHeader("USER-AGENT").toLowerCase()
                    .indexOf("firefox") > 0 ? false : true) {
                filedisplay = "attachment;filename="
                        + URLEncoder.encode(filedisplay, "UTF-8");
            } else {
                filedisplay = "attachment;filename="
                        + new String(filedisplay.getBytes(), "ISO-8859-1");
            }
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", filedisplay);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");

            Set<Entry<String, Object>> entrySet = dataMap.entrySet();
            for (Entry<String, Object> entry : entrySet) {
                int rowaccess = 100;// 内存中缓存记录行数
                SXSSFWorkbook wb = new SXSSFWorkbook(rowaccess);
                Font font = wb.createFont();
                font.setFontName("宋体");
                font.setFontHeightInPoints((short) 16);
                CellStyle style = wb.createCellStyle();
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);

                String objectname = entry.getKey();
                String file = getRealPath(request) + "/"
                        + getFileName(objectname) + ".xls";
                fileNames.add(file);
                FileOutputStream o = new FileOutputStream(file);

                @SuppressWarnings("unchecked")
                Map<Object, List<Object[]>> objData = (Map<Object, List<Object[]>>) entry
                        .getValue();
                Set<Entry<Object, List<Object[]>>> objDataEntrySet = objData.entrySet();
                for (Entry<Object, List<Object[]>> objDataEntry : objDataEntrySet) {
                    // 循环页签
//                    Object key = objDataEntry.getKey();
                    Sheet sheet = wb.createSheet(title);// sheet页签名
                    sheet.setDefaultColumnWidth(15);// 默认宽度
                    
                    Row row = sheet.createRow((int) 0);
                    row = sheet.createRow((int) 0);
                    for (int i = 0; i < headers.length; i++) {
                        row.createCell(i).setCellValue(headers[i]);// 第一行列名
                    }
                    List<Object[]> list = objDataEntry.getValue();
                    for (int i = 0; i < list.size(); i++) {
                        Object[] obj = list.get(i);
                        row = sheet.createRow((int) i + 1);
                        for (int j = 0; j < obj.length; j++) {
                            if (null == obj[j]) {
                                row.createCell(j).setCellValue("");
                            } else {
                                row.createCell(j).setCellValue(
                                        String.valueOf(obj[j]));
                            }
                        }
                        // 每当行数达到设置的值就刷新数据到硬盘,以清理内存
                        if (i % rowaccess == 0) {
                            ((SXSSFSheet) sheet).flushRows();
                        }
                    }

                }

                wb.write(o);
                o.close();

                // 循环结束
            }

            out = response.getOutputStream();

            File[] srcfile = new File[fileNames.size()];
            for (int i = 0, n1 = fileNames.size(); i < n1; i++) {
                srcfile[i] = new File(fileNames.get(i));
            }
            ZipFiles(srcfile, zip);
            FileInputStream inStream = new FileInputStream(zip);
            byte[] buf = new byte[4096];
            int readLength;
            while (((readLength = inStream.read(buf)) != -1)) {
                out.write(buf, 0, readLength);
            }
            inStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 获取文件名字
    public static String getFileName(String title) {
        // 文件名获取
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String f = title + format.format(date);
        return f;
    }

    // 获取项目的绝对地址
    public static String getRealPath(HttpServletRequest request) {
        String realPath = request.getSession().getServletContext()
                .getRealPath("/");
        // System.out.println(realPath);
        return realPath;
    }

    // 压缩文件
    public static void ZipFiles(File[] srcfile, File zipfile) {
        byte[] buf = new byte[1024];
        try {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                    zipfile));
            for (int i = 0; i < srcfile.length; i++) {
                FileInputStream in = new FileInputStream(srcfile[i]);
                out.putNextEntry(new ZipEntry(srcfile[i].getName()));
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
                out.closeEntry();
                in.close();
            }
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}